# -*- coding:utf-8 -*-

import gevent
import functools
import tornado.web
import tornado.ioloop

import time
# import config
import uuid

from tornado.concurrent import Future

session_timeout = 600


class BaseHandler(tornado.web.RequestHandler):
    __session_cache = {}

    def __init__(self, application, request, **kwargs):
        super(BaseHandler, self).__init__(application, request, **kwargs)
        # 自定义session
        secret = self.get_secure_cookie("secret")
        if not secret or BaseHandler.get_session(secret) == "":
            secret = str(uuid.uuid4())
            self.set_secure_cookie("secret", secret.encode("unicode_escape"), expires=time.time() + session_timeout)
            BaseHandler.set_session(secret, {})
        self.session = BaseHandler.get_session(secret)

    def get_current_user(self):
        _login_enable = 0  # config.read_config(sec="LOGIN", key="enable")
        if "1" == _login_enable:
            user = self.get_secure_cookie("pkg_username")
        else:
            user = "NoAccountCheck"
        return user

    @classmethod
    def get_session(cls, key):
        cls.clean_timeout()
        if key in cls.__session_cache:
            cls.update_cache(key)
            return cls.__session_cache[key]["session"]
        return ""

    @classmethod
    def set_session(cls, key, value):
        if isinstance(key, str) or isinstance(key, int):
            cls.__session_cache[key] = {"timeout": time.time() + session_timeout, "session": value}
        else:
            raise ValueError("Wrong type of key!", "in set_session() of webBase.py")

    @classmethod
    def update_cache(cls, key):
        if key in cls.__session_cache:
            cls.__session_cache[key]["timeout"] = time.time() + session_timeout
        else:
            cls.__session_cache[key] = {"timeout": time.time() + session_timeout, "session": {}}

    @classmethod
    def clean_timeout(cls):
        for k, v in cls.__session_cache.items():
            if v["timeout"] <= time.time():
                cls.__session_cache.pop(k)


# Asynchronous gevent decorator
def gfuture(func):
    @functools.wraps(func)
    def f(*args, **kwargs):
        loop = tornado.ioloop.IOLoop.current()
        future = Future()

        def call_method():
            try:
                result = func(*args, **kwargs)
                loop.add_callback(functools.partial(future.set_result, result))
            except Exception, e:
                loop.add_callback(functools.partial(future.set_exception, e))
        gevent.spawn(call_method)
        return future
    return f
